package org.example.bean;

import lombok.extern.slf4j.Slf4j;
import org.example.model.Band;
import org.example.processor.BandMappingProcessor;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import javax.sql.DataSource;

@Slf4j
@Configuration
@EnableBatchProcessing
public class BandImportJobConfig {
    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;

    @Autowired
    public DataSource dataSource;

    @Bean
    public JdbcBatchItemWriter<Band> writer() {
        JdbcBatchItemWriter<Band> writer = new JdbcBatchItemWriter<>();
        writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
        writer.setSql("INSERT INTO band(name) VALUES (:name)");
        writer.setDataSource(dataSource);

        return writer;
    }

    @Bean
    public FlatFileItemReader<Band> reader() {
        FlatFileItemReader<Band> reader = new FlatFileItemReader<>();
        // Where your input is
        reader.setResource(new ClassPathResource("band.csv"));
        // How to read your input
        reader.setLineMapper(new DefaultLineMapper<Band>() {{
            setLineTokenizer(new DelimitedLineTokenizer() {{
                // Mapping to property [name] in User model
                setNames("name");
            }});
            setFieldSetMapper(new BeanWrapperFieldSetMapper<Band>() {{
                setTargetType(Band.class);
            }});
        }});

        return reader;
    }

    @Bean
    public BandMappingProcessor processor() {
        return new BandMappingProcessor();
    }


    @Bean
    public Step step1() {
        // Split to 3 blocks make some acceleration
        return stepBuilderFactory.get("step1").<Band, Band>chunk(3)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .build();
    }

    /**
     * Instant trigger
     * @return
     */
    @Bean
    public Job importBandJob() {
        log.info("Batch job [importBandJob] has registered!");
        return jobBuilderFactory.get("importBandJob")
                // One by one increase job id
                .incrementer(new RunIdIncrementer())
                // You can define and assign more step HERE!
                .flow(step1())
                .end()
                .build();
    }
}
